package org.luxor.commons.lock4j;

import org.luxor.commons.lock4j.core.LockExecutor;
import org.luxor.commons.lock4j.core.LockInfo;
import org.luxor.commons.lock4j.util.LockUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

/**
 * 锁模板方法
 *
 * @author zengzh
 * @since 1.0.0
 */
public class LockTemplate {
    private static final Logger log = LoggerFactory.getLogger(LockTemplate.class);

    private static final String PROCESS_ID = LockUtil.getLocalMAC() + LockUtil.getJvmPid();

    private LockExecutor lockExecutor;

    public void setLockExecutor(LockExecutor lockExecutor) {
        this.lockExecutor = lockExecutor;
    }

    /**
     * 加锁
     *
     * @param key     锁名称
     * @param expire  锁过期时间(单位:毫秒)
     * @param timeout 获取锁超时时间(单位:毫秒)
     */
    public LockInfo lock(String key, long expire, long timeout) throws Exception {
        Assert.isTrue(timeout > 0, "tryTimeout must more than 0");
        long start = System.currentTimeMillis();
        int acquireCount = 0;
        String value = PROCESS_ID + Thread.currentThread().getId();
        while (System.currentTimeMillis() - start < timeout) {
            boolean result = lockExecutor.acquire(key, value, expire);
            acquireCount++;
            if (result) {
                return new LockInfo(key, value, expire, timeout, acquireCount);
            }
        }
        log.error("lock failed, try {} times", acquireCount);
        return null;
    }

    /**
     * 解锁
     *
     * @param lockInfo 要解除的锁信息
     */
    public boolean releaseLock(LockInfo lockInfo) {
        String lockKey = lockInfo.getLockKey();
        String lockValue = lockInfo.getLockValue();
        return lockExecutor.releaseLock(lockKey, lockValue);
    }
}
